home *** CD-ROM | disk | FTP | other *** search
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 1
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- +-----------------------------------+
- | |
- | evalx.c |
- | |
- +-----------------------------------+
-
- Algebraic Expression Evaluator/Parser
- James P. Hawkins - WA2WHV
- P.O. Box 9146,
- Trenton, NJ 08650
- September 11, 1990
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 2
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- DESCRIPTION
- _____________________________________________________________________
-
- Evalx is a convenient, powerful function which, when passed
- an ASCII string representing an algebraic expression of
- floating point numbers and math functions, will return the
- answer in a single floating point number. The expression may
- contain operators +, -, /, *, ^ and (). Parens may be nested
- more times than most would need. Embedded white space is
- allowed.
-
- Example: 2.0 + 22 * (3.1415926 * (2.4 - 33) + 3.3 ^ 2)/43 +
- (22 / 3.14)^3
-
- Also, functions are available and can be used as shown in the
- following example:
-
- ((5.6 ^ 2 + sin(30 * (2 * 3.14159)/360)))
-
- which is 5.6 squared plus sin of 30 degrees. The sin
- function uses the angle in radians, so the conversion ratio
- is included in the argument to the sin function.
-
- MATH FUNCTIONS
- _____________________________________________________________________
-
- The expression may contain digits representing decimal numbers
- or the following math functions:
-
- sin(expstr) - sine of an angle in radians
- cos(expstr) - cosine of an angle in radians
- exp(expstr) - exponentiate
- log(expstr) - natural log
- int(expstr) - integerize (truncate to right of dec .)
- sqr(expstr) - square root
- abs(expstr) - absolute value
- atn(expstr) - arctan
- rnd(expstr) - random number gen
- tan(expstr) - tangent of an angle
- fact(expstr) - factorial
-
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 3
-
-
-
-
-
-
-
-
-
-
-
- CALLING FORMAT
- _____________________________________________________________________
-
- A pointer to the string expression is passed to evalx() which
- returns a resulting value as a double precision floating
- point number.
-
- double value; /* declare a double */
- double evalx(char *expstr); /* declare the function */
-
- value = evalx(expstr); /* evaluate the expression and */
- /* return it in value */
-
- where: expstr is the char string representing the expression
- to be evaluated. The string must be NULL terminated.
-
- To test for an error, simply do a switch(errorflg). Errorflg
- must be declared as an extern int in the calling program. A
- zero value indicates no error, otherwise the error condition
- is defined as follows:
-
- ERRFATAL - FATAL ERROR
- ERRSYNTAX - SYNTAX ERROR
- ERROVFLOW - OVERFLOW ERROR
- ERRSQRT- SQUARE ROOT OF NEG NUMBER ERROR
- ERRFACT - FACTORIAL OF NEG or NUM > 33 ERROR
- ERRFUNC - UNKNOWN FUNCTION ERROR
- ERRILLVAR - ILLEGAL VARIABLE TYPE
-
-
- EXAMPLE PROGRAM
- _____________________________________________________________________
-
- The following is a program example of the use of evalx().
- When compiled, it provides a command which when given an
- expression as an argment (no embedded spaces) will print the
- answer. Or when invoked with no argment, will prompt for
- expression input. Embedded space IS allowed when prompted.
- The parser itself handles embedded spaces, however, an
- argument to a command with embedded spaces will be
- interpreted by the command shell as multiple arguments unless
- it is surrounded by quotes. Also note that in the UNIX
- shell, parens must be "hidden" from the shell with a
- preceding '\'.
-
- #include <stdio.h>
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 4
-
-
- #include "evalx.h" /* Must be included error constants */
-
- double evalx(char *ptr); /* declare evalx() */
-
- extern int errorflg; /* declare external errorflg */
-
- main(int argc, char **argv)
- {
- double val; /* declare double for result */
- int exitflg = 0;
- char str[80]; /* storage for expression string */
-
- while(1)
- {
- /*
- * If expression was in command argument then
- * Compute, print, then quit.
- * Else, wait for an input to be typed, compute,
- * print, then wait again.
- */
- if(argc > 1)
- {
- strcpy(str, argv[1]);
- exitflg++;
- }
- else
- {
- printf("Input Expression:\n");
- gets(str);
- }
- val = evalx(str); /* Evaluate the expression */
-
- /* Test error condition if any */
- switch(errorflg)
- {
- case 0: /* NO ERROR, PRINT RESULT */
- printf("Result=%g\n", val);
- if(exitflg)
- {
- exit(0);
- }
- break;
- case ERRFATAL:
- printf("Fatal error\n");
- break;
- case ERRSYNTAX:
- printf("Syntax error\n");
- break;
- case ERROVFLOW:
- printf("Overflow error\n");
- break;
- case ERRSQRT:
- printf("Square root of neg number error\n");
- break;
- case ERRFACT:
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 5
-
-
- printf("Factorial error\n");
- break;
- case ERRFUNC:
- printf("Unknown math function error\n");
- break;
- case ERRILLVAR:
- printf("Illegal variable error\n");
- break;
- default:
- break;
- }
- }
- }
-
- ALGORITHM
- _____________________________________________________________________
-
- The evalx() function loops until a null character is
- encountered.
-
- t the beginning of each loop, the function class() is called.
- This is in the file class.c which MUST be compiled and linked
- with evalx.c and the program. Class() classifies each item
- as a field of type OPCLASS, NMCLASS or FNCLASS. OPCLASS is
- returned if, an operator +,-,/,*,^,(,) is encountered.
- NMCLASS is returned if a number is scanned and FNCLASS is
- returned if the field is a function containing another
- expression such as sin(22 + 33). The class of field
- determines what action, evalx is to take next.
-
- There are two stacks, one for numbers or operands called
- double opndstack[] and one for operators char opstack[].
- When a number is encountered in the string it is converted to
- a double precision floating point number and simply pushed
- onto the operand stack. When an operator, other than parens,
- is encountered, the stackop() function is called.
-
- Stackop() uses precedence rules to determine what to do with
- the current operator. The precedence of an operator is
- computed by passing the operator to the preced() function.
- The preced function returns a value of 1 for the operators
- '+' and '-', 2 for '*' and '/' and finally 3 for '^' or
- exponentiate. The precedence of the current operator is
- compared with the precedence of the operator on the top of
- the stack. If precedence of current operator is higher than
- the operator on top of the stack or the operator stack is
- empty, the precedence test has "passed" so just push the
- current operator onto the operator stack. If the current
- operator precedence is less than or equal to the operator on
- the top of the stack, the topmost operator is applied to the
- two topmost two operands in the operand stack by a call to
- unstack(). Unstack() is called until either the stack is
- empty or the precedence test passes in which the current
- operator is finally placed on the operator stack. That is,
- the unstack() function does the actual arithmetic operations
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 6
-
-
- in evalx(). Examination of the unstack() function will show
- that it contains a simple switch() statement which uses the
- operator to determine which operation is to be performed on
- the topmost operands. Then, the operator and operand stcks
- are popped.
-
- When an open parenthesis '(' operator is encountered, evalx()
- is recursively called to evaluate whatever is inside of a
- pair of balanced parenthesis. When a close paren ')'
- operator is encountered, the cleanup() function is called
- which simply cleans up both stacks by doing all remaining
- calculations. Then evalx() returns to either a higher
- instance of evalx() or the original calling function. Since
- the operator opstack[] and the operand stack opndstack[] are
- automatic variables, the stack size need only be as large as
- there are precedence values, because each instance of nested
- parens results in another call to evalx(), which creates
- another instance of these small stacks. Each time evalx()
- returns, that instance of stacks is no longer needed.
- Remember that automatic generation is implicitly handled by
- stack management. Throughout the evaluation, eoexpr is a
- global string place holder. This probably could have been
- handled with automatic variables also. When the first or
- highest instance of evalx() is finished when the end of
- string is encountered, a final cleanup() is done to evaluate
- whatever is left on the operand stack.
-
- If the class() function encounters a function, it copies
- everything within balanced parenthesis of the function and
- places it in the field[] array. Then mathcall() is called
- with this string passed to it. Mathcall() does a string
- search for the math function in a table which consists of
- name, function address pairs. If the function, such as "sin"
- is encountered, the string value that is passed to mathcall()
- is evaluated by a call to evalx() (another recursion), and
- the returned number is passed to the appropriate function.
- The return value of the function is returned by mathcall() to
- the calling instance of evalx() which is put on the operator
- or operand stack and treated like any other number for the
- rest of the evaluation within the current level of
- parenthesis. If a function field is encountered, the
- mathcall() function is called.
-
- The operation of the class function is left as an exersize
- for the reader!
-
- COMPILATION WITH EXAMPLE PROGRAM
- _____________________________________________________________________
-
- Included in this package are the following files:
-
- calc.c - Example calling program
- evalx.c - Evaluator.
- class.c - Expression field classifier.
- evalx.h - Header for evalx.c and class.c
-
-
-
- EVALX.DOC Monday, September 17, 1990 Page 7
-
-
- This must be #included in calling program!
- calc.mak - Makefile for Microsoft 5.1 make
- evalx.doc - This document
- calc.exe - Example program compiled. Try it!
-
- This program was compiled using Microsoft C 5.1. If you have
- Microsoft C 5.1 use make as follows.
-
- make calc.mak calc.exe
-
- However you compile the program, class.c must also be linked
- in. Also, the calling program must have #include "evalx.h"
- and a declaration extern int errorflg.
-
- IMPORTANT NOTICE!
- _____________________________________________________________________
-
- This software is free, however I would appreciate a small
- donation of $5.00 if you find it useful, or whatever you wish
- to help support my continued efforts in providing more useful
- software. Please send to address below. Thankyou! You may
- distribute this software by any means, but you may NOT charge
- for this software by itself, except to cover distribution
- costs. You may use it in software you develop and charge for
- your software. Unless drastically altered, please do not
- remove my name as author from the software. All
- documentation and files must be included.
-
- WARRANTEE: This program is being provided "AS IS". It is up
- to the user to determine the suitability of this program for
- their purposes. The user takes all responsibility for any
- direct or consequential damages.
-
- _____________________________________________________________________
-
- James P. Hawkins - WA2WHV
- P.O. Box 9146
- Trenton, NJ 08650
-
- CompuServe 76446,613
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ----------------end-of-author's-documentation---------------
-
- Software Library Information:
-
- This disk copy provided as a service of
-
- Public (software) Library
-
- We are not the authors of this program, nor are we associated
- with the author in any way other than as a distributor of the
- program in accordance with the author's terms of distribution.
-
- Please direct shareware payments and specific questions about
- this program to the author of the program, whose name appears
- elsewhere in this documentation. If you have trouble getting
- in touch with the author, we will do whatever we can to help
- you with your questions. All programs have been tested and do
- run. To report problems, please use the form that is in the
- file PROBLEM.DOC on many of our disks or in other written for-
- mat with screen printouts, if possible. PsL cannot debug pro-
- programs over the telephone, though we can answer questions.
-
- Disks in the PsL are updated monthly, so if you did not get
- this disk directly from the PsL, you should be aware that the
- files in this set may no longer be the current versions. Also,
- if you got this disk from another vendor and are having prob-
- lems, be aware that some files may have become corrupted or
- lost by that vendor. Get a current, working disk from PsL.
-
- For a copy of the latest monthly software library newsletter
- and a list of the 2,000+ disks in the library, call or write
-
- Public (software) Library
- P.O.Box 35705 - F
- Houston, TX 77235-5705
-
- 1-800-2424-PSL
- MC/Visa/AmEx
-
- Outside of U.S. or in Texas
- or for general information,
- Call 1-713-524-6394
-
- PsL also has an outstanding
- catalog for the Macintosh.
-